<?php

$tabJour = array( 'lundi'
                , 'mardi'
                , 'mercredi'
                , 'jeudi'
                , 'vendredi'
                , 'samedi'
                , 'dimanche' );

$tabMois = array(  '1' => 'janvier'
                ,  '2' => 'fevrier'
                ,  '3' => 'mars'
                ,  '4' => 'avril'
                ,  '5' => 'mai'
                ,  '6' => 'juin'
                ,  '7' => 'juillet'
                ,  '8' => 'aout'
                ,  '9' => 'septembre'
                , '10' => 'octobre'
                , '11' => 'novembre'
                , '12' => 'décembre');

/**
 * @class  DateSql date.lib.php
 *   
 * @brief  Classe de gestion des date au format SQL.
 *
 * @author  Jeremie Fouche
 *  
 * Cette classe permet de manipuler des dates au format SQL, et de pouvoir
 *   recuperer des infos la concernant.  
 */
class DateSql
{
  /**
   * @brief  Recupere la date actuelle
   * 
   *@return DateSql      
   */
  function get_current()
  {
    return date("Y-m-d");
  }
  
  /**
   * @brief  Cree une DateSql
   *    
   * @param $jour   jour
   * @param $mois   mois
   * @param $annee  annee   
   * 
   *@return DateSql      
   */
  function create($jour, $mois, $annee)
  {
    return sprintf( '%4d-%02d-%02d'
                  , $annee
                  , $mois
                  , $jour );
  }

  /**
   * @brief  Retourne un tableau representatif d'une date au format Sql
   *
   * @param $dateSql  la date a analyser
   *      
   * @return  Retourne un tableau contenant les infos d'une date
   */
  function get_infos($dateSql)
  {                             
    $infos = false;             
    $tab = explode('-', $dateSql);
    if ( is_array($tab) && (count($tab)==3) )
    {                           
      $tsDate = mktime( 0, 0, 0
                      , (int) $tab[1]
                      , (int) $tab[2]
                      , (int) $tab[0] );
      $iJour  = (date('w', $tsDate) + 6) % 7;

      $infos = array( 'jour'       => (int) $tab[2]
                    , 'nomJour'    => $GLOBALS['tabJour'][$iJour]
                    , 'mois'       => (int) $tab[1]
                    , 'nomMois'    => $GLOBALS['tabMois'][(int) $tab[1]]
                    , 'annee'      => (int) $tab[0]
                    , 'timestamp'  => $tsDate
                    , 'idxJour'    => $iJour
                    , 'nbJours'    => date('t', $tsDate) );
    }
    return $infos;
  }

  /**
   * @brief  Indique si une date SQL est valide
   * 
   * @param $dateSql  date SQL
   *
   * @return  Retourne true si la date est valide, false sinon      
   */     
  function is_valide($dateSql)
  {
    $infos = DateSql::get_infos($dateSql);
    return is_array($infos)
        && checkdate($infos['mois'], $infos['jour'], $infos['annee']);
  }

  /**
   * @brief  Retourne l age d une personne en fonction de sa date de naissance.
   *
   * @param $dateSql  date de naissance SQL
   *
   * @return  Retourne l'age correspondant a la date de naissance fournie
   */
  function get_age($dateSql)
  {
    $age = false;
    if ( DateSql::isValide($dateSql) )
    {
      $today      = DateSql::getCurrent();
      $infosToday = DateSql::getInfos($today);
      $infos      = DateSql::getInfos($dateSql);
      $age        = $infosToday['annee'] - $infos['annee'];

      if ($infos['mois'] > $infosToday['mois'])
      {
        $age--;
      }
      else if ( ($infos['mois'] == $infosToday['mois'])
             && ($infos['jour']  > $infosToday['jour']) )
      {
        $age--;
      }
    }
    return $age;
  }

  /**
   * @brief  Retourne la date du mois suivant (pouvant etre l annee suivante)
   *
   * @param $dateSql  date SQL
   *
   * @return  Retourne une DateSql correspondant au mois suivant.
   */
  function get_mois_suivant($dateSql)
  {
    $dateSqlSuiv = false;

    if ( DateSql::is_valide($dateSql) )
    {
      $infos     = DateSql::get_infos($dateSql);
      $anneeSuiv = $infos['annee'];
      $moisSuiv  = $infos['mois'] + 1;

      if ($moisSuiv == 13)
      {
        $moisSuiv = 1;
        $anneeSuiv++;
      }
      $dateMoisSuiv = DateSql::create(1, $moisSuiv, $anneeSuiv);
      $infosSuiv    = DateSql::get_infos($dateMoisSuiv);
      
      $jour = min($infos['jour'], $infosSuiv['nbJours']);

      $dateSqlSuiv = DateSql::create($jour, $moisSuiv, $anneeSuiv);
    }

    return $dateSqlSuiv;
  }

  /**
   * @brief  Retourne la date du mois precedent (pouvant etre l annee precedente)
   *
   * @param $dateSql  date SQL
   *
   * @return  Retourne une DateSql correspondant au mois precedent.
   */
  function get_mois_precedent($dateSql)
  {
    $dateSqlPrec = false;

    if ( DateSql::is_valide($dateSql) )
    {
      $infos     = DateSql::get_infos($dateSql);
      $anneePrec = $infos['annee'];
      $moisPrec  = $infos['mois'] - 1;

      if ($moisPrec == 0)
      {
        $moisPrec = 12;
        $anneePrec--;
      }
      $dateMoisPrec = DateSql::create(1, $moisPrec, $anneePrec);
      $infosPrec    = DateSql::get_infos($dateMoisPrec);

      $jour = min($infos['jour'], $infosPrec['nbJours']);
      
      $dateSqlPrec = DateSql::create($jour, $moisPrec, $anneePrec);
    }

    return $dateSqlPrec;
  }

  /**
   * @brief  Transforme une date au format FR en DateSql 
   *
   * @param $dateFr  date au format FR (JJ/MM/AAAA ou JJ-MM-AAAA)
   *
   * @return  Retourne la DateSql correspondante.
   */
  function Fr2Sql($dateFr)
  {
    $dateSql = false;
    if (ereg("([0-9]{1,2})[-/]([0-9]{1,2})[-/]([0-9]{4})", $dateFr, $regs))
    {
      $dateSql = DateSql::create($regs[1], $regs[2], $regs[3]);
    }
    return $dateSql;
  }
  
  /**
   * @brief  Transforme une date DateSql en date au format FR (JJ/MM/AAAA) 
   *
   * @param $dateSql  date SQL
   *
   * @return  Retourne une chaine au format FR.
   */
  function Sql2Fr($dateSql)
  {
    $dateFr = false;
    if (ereg("([0-9]{4})-([0-9]{1,2})-([0-9]{1,2})", $dateSql, $regs))
    {
      $dateFr = sprintf('%02d/%02d/%d', $regs[3], $regs[2], $regs[1]);
    }
    return $dateFr;
  }

  /**
   * @brief  Indique si une date est dans le week-end (samedi ou dimanche) 
   *
   * @param $dateSql  date SQL
   *
   * @return  Retourne true si la date est samedi ou dimanche, false sinon
   */
  function is_weekend($dateSql)
  {
    return (DateSql::get_infos($dateSql, 'idxJour') >= 5);
  }

  /**
   * @brief  Indique le nombre de jour ouvres du mois en cours 
   *
   * @param $dateSql  date SQL
   *
   * @return  le nb de jour ouvres
   */
  function get_nb_jour_ouvres($dateSql)
  {
    $delta = array( array(20,20,20,20,20,20,20)
                  , array(20,21,21,21,21,21,20)
                  , array(21,22,22,22,22,21,20)
                  , array(22,23,23,23,22,21,21)
                  );

    $info        = DateSql::get_infos($dateSql);
    $nb_after_28 = $info['nbJours'] - 28;
    $day_for_29  = jddayofweek(gregoriantojd($info['mois'], 29, $info['annee']));

    return $delta[$nb_after_28][$day_for_29];  
  }
}

?>
